package com.tools.web.interceptor.quota;

import com.tools.common.object.Note;
import com.tools.common.thread.Timeunit;
import com.tools.middle.redis.client.JedisPlus;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;

/**
 * 使用 JedisPlus 客户端操作单机 Redis 实现的配额限制拦截器
 * */
@Note("使用 JedisPlus 客户端操作单机 Redis 实现的配额限制拦截器")
public final class JedisPlusQuotaManager extends AbsQuotaManager implements QuotaRedisLuaScript {

    @Note("操作 Redis 的单机客户端")
    private final JedisPlus jedisPlus;

    public JedisPlusQuotaManager(JedisPlus jedisPlus, QuotaSource source) {
        super(source);
        this.jedisPlus = Objects.requireNonNull(jedisPlus, "操作 Redis 的单机客户端 JedisPlus 不能为 null");
    }

    @Override
    protected boolean protected_checkIsAllow(QuotaLimit quotaLimit, HttpServletRequest request, HttpServletResponse response) throws Exception {
        String action = quotaLimit.action();
        int allow = quotaLimit.allow();
        String uniqueID = super.protected_getUniqueID(quotaLimit, request, response);
        String key = super.protected_getKey(action, uniqueID);
        try {
            Long result = (Long) this.jedisPlus.eval(CHECK_ALLOW, 1, key, allow);
            if(result != null && result == 1) return true;
            response.getWriter().write(super.protected_getQuotaErrorMessage(quotaLimit, uniqueID));
            return false;
        } finally {
            this.jedisPlus.close();
        }
    }

    @Override
    public void increaseQuota(String action, Object uniqueID, long expiration, Timeunit timeunit) {
        String key = super.protected_getKey(action, uniqueID.toString());
        long expirationSecond = Timeunit.toSecond(expiration, timeunit);
        try {
            this.jedisPlus.eval(INCREASE, 1, key, expirationSecond);
        } finally {
            this.jedisPlus.close();
        }
    }
}
